package com.openspring.framework.extend.shiro;

import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;

import com.openspring.platform.model.LoginUser;
import com.openspring.platform.model.Role;
import com.openspring.platform.model.User;
//import com.openspring.platform.service.RoleService;
import com.openspring.platform.service.SecurityService;
import com.openspring.platform.service.UserService;

public class ShiroJdbcRealm extends AuthorizingRealm {

	private UserService userService;
	//private RoleService roleService;
	private SecurityService securityService;
	
	@Resource(name = "userService")
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	
//	@Resource(name = "roleService")
//	public void setRoleService(RoleService roleService) {
//		this.roleService = roleService;
//	}

	@Resource(name = "securityService")
	public void setSecurityService(SecurityService securityService) {
		this.securityService = securityService;
	}
	
	@Override
	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		LoginUser loginUser = (LoginUser) principals.fromRealm("ShiroJdbcRealm").iterator().next();
		User user = userService.load(loginUser.getId());
		if (user != null) {
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
			List<Role> roles = userService.getRoles(user.getId());
			for(Role role : roles) {
				List<Map<String, Object>> permissions = securityService.findOperatorPermissions(role.getId());
				for(Map<String, Object> permission : permissions) {
					info.addStringPermission(permission.get("resource_name").toString());
					info.addStringPermission(permission.get("resource_name") + ":" + permission.get("operator_name"));
				}
			}
			return info;
		} else {
			return null;
		}
	}

	@Override
	/**
	 * 认证回调函数, 登录时调用.
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		User user = userService.get(token.getUsername(), String.valueOf(token.getPassword()));
		if (user != null) {
			token.setPassword(user.getPassword().toCharArray());
			return new SimpleAuthenticationInfo(new LoginUser(user), user.getPassword(), "ShiroJdbcRealm");
		} else {
			return null;
		}
	}
	
	/**
	 * 更新用户授权信息缓存.
	 */
	public void clearCachedAuthorizationInfo(String principal) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, "ShiroJdbcRealm");
		clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除所有用户授权信息缓存.
	 */
	public void clearAllCachedAuthorizationInfo() {
		Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
		if (cache != null) {
			for (Object key : cache.keys()) {
				cache.remove(key);
			}
		}
	}
}
